package com.ai.zhly.util;

import java.text.DecimalFormat;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import com.ai.dmc.index.common.bean.TmpXqBean;

import net.sf.json.JSONArray;
import net.sf.json.JSONObject;

public class ConvertUtil {
	
	//搜索uid请求
	private static String uidUrl = "http://map.baidu.com/su?wd=$xqName$&cid=127&type=0&newmap=1&b=(12921011.63135%2C4792497.874055%3B13018419.63135%2C4853105.874055)&t=1476350355424&pc_ver=2";
	private static String uidUrl2 = "http://map.baidu.com/?newmap=1&reqflag=pcmap&biz=1&from=webmap&da_par=direct&pcevaname=pc4.1&qt=s&da_src=searchBox.button&wd=$xqName$&c=131&src=0&wd2=&sug=0&l=19&b=(12984102.105,4884975.029999999;12984863.105,4885448.529999999)&from=webmap&biz_forward={%22scaler%22:1,%22styles%22:%22pl%22}&sug_forward=&tn=B_NORMAL_MAP&nn=0&u_loc=13047688,3722215&ie=utf-8&t=1476363734313";
	//搜索边界请求
	private static String geoUrl = "http://map.baidu.com/?newmap=1&reqflag=pcmap&biz=1&from=webmap&da_par=direct&pcevaname=pc4.1&qt=ext&uid=$UID$&c=131&ext_ver=new&tn=B_NORMAL_MAP&nn=0&u_loc=13047688,3722215&ie=utf-8&l=12&b=(12923270.56,4795043.47;13020678.56,4855651.47)&t=1476351773749";
	
	private static Double EARTHRADIUS = 6370996.81;
    private static Double[] MCBAND = {12890594.86, 8362377.87, 5591021d, 3481989.83, 1678043.12, 0d};
    private static Double[] LLBAND = {75d, 60d, 45d, 30d, 15d, 0d};
    private static Double[][] MC2LL = {{1.410526172116255e-8, 0.00000898305509648872, -1.9939833816331, 200.9824383106796, -187.2403703815547, 91.6087516669843, -23.38765649603339, 2.57121317296198, -0.03801003308653, 17337981.2}, {-7.435856389565537e-9, 0.000008983055097726239, -0.78625201886289, 96.32687599759846, -1.85204757529826, -59.36935905485877, 47.40033549296737, -16.50741931063887, 2.28786674699375, 10260144.86}, {-3.030883460898826e-8, 0.00000898305509983578, 0.30071316287616, 59.74293618442277, 7.357984074871, -25.38371002664745, 13.45380521110908, -3.29883767235584, 0.32710905363475, 6856817.37}, {-1.981981304930552e-8, 0.000008983055099779535, 0.03278182852591, 40.31678527705744, 0.65659298677277, -4.44255534477492, 0.85341911805263, 0.12923347998204, -0.04625736007561, 4482777.06}, {3.09191371068437e-9, 0.000008983055096812155, 0.00006995724062, 23.10934304144901, -0.00023663490511, -0.6321817810242, -0.00663494467273, 0.03430082397953, -0.00466043876332, 2555164.4}, {2.890871144776878e-9, 0.000008983055095805407, -3.068298e-8, 7.47137025468032, -0.00000353937994, -0.02145144861037, -0.00001234426596, 0.00010322952773, -0.00000323890364, 826088.5}};
    private static Double[][] LL2MC = {{-0.0015702102444, 111320.7020616939, 1704480524535203d, -10338987376042340d, 26112667856603880d, -35149669176653700d, 26595700718403920d, -10725012454188240d, 1800819912950474d, 82.5}, {0.0008277824516172526, 111320.7020463578, 647795574.6671607, -4082003173.641316, 10774905663.51142, -15171875531.51559, 12053065338.62167, -5124939663.577472, 913311935.9512032, 67.5}, {0.00337398766765, 111320.7020202162, 4481351.045890365, -23393751.19931662, 79682215.47186455, -115964993.2797253, 97236711.15602145, -43661946.33752821, 8477230.501135234, 52.5}, {0.00220636496208, 111320.7020209128, 51751.86112841131, 3796837.749470245, 992013.7397791013, -1221952.21711287, 1340652.697009075, -620943.6990984312, 144416.9293806241, 37.5}, {-0.0003441963504368392, 111320.7020576856, 278.2353980772752, 2485758.690035394, 6070.750963243378, 54821.18345352118, 9540.606633304236, -2710.55326746645, 1405.483844121726, 22.5}, {-0.0003218135878613132, 111320.7020701615, 0.00369383431289, 823725.6402795718, 0.46104986909093, 2351.343141331292, 1.58060784298199, 8.77738589078284, 0.37238884252424, 7.45}};
    private static String dealSuccess = "1";
    private static String dealFail = "3";
    
	/**
	 * @desc 根据小区名称，获取百度经纬度边界序列
	 * 
	 * @param oldBean
	 * @return
	 */
	public static TmpXqBean convert(TmpXqBean oldBean){
		
		String xqName = oldBean.getName();
		oldBean.setHasGeo(dealFail);
		if (xqName == null || xqName.trim().equals("")) {
			return oldBean;
		}
		//1.获取UID列表，两种搜索方式
		List<String>uids = getUids2(xqName);
		List<String>uids2 = getUids(xqName);
		if (uids!=null) {
			uids.addAll(uids2);
		}else {
			uids = uids2;
		}
		
		//2.获取墨卡托GEO，遍历UID列表，获取到geo则停止遍历
		String geo =null;
		if (uids!=null && uids.size()>0) {
			for (int i = 0; i < uids.size(); i++) {
				if (uids.get(i) == null ||  uids.get(i).trim().equals("")) {
					continue;
				}
				String [] s = uids.get(i).split("\\$");
				String uid = s.length>5?s[5]:null;
				String uname = s.length>5?s[3]:null;
				if (uid == null ||  uid.trim().equals("")) {
					continue;
				}
				//根据uid获取geo
				Map<String, String>geoMap = getGeo(uid);
				geo = geoMap.get("geo");
				if (geo!=null && !geo.trim().equals("")) {
					oldBean.setGeo(geo);
					oldBean.setHasGeo(dealSuccess);
					oldBean.setuId(uid);
					oldBean.setuName(uname);
					String core = geoMap.get("core");
					if (core!=null && core.split(",").length==2) {
						oldBean.setLng(core.split(",")[0]);
						oldBean.setLat(core.split(",")[1]);
					}
					break;
				}
			}
		}else {
			return oldBean;
		}
		//3.墨卡托转经纬度
		if (geo !=null&&!geo.trim().equals("")) {
	        String []geos = geo.split(",");
	        String lngLatList = "";
	        for (int i = 1; i < geos.length; i=i+2) {
				double tLng =  Double.valueOf(geos[i-1]);
				double tLat = Double.valueOf(geos[i]);
				Map<String, Double> location = convertMC2LL(tLng, tLat);
		        lngLatList = lngLatList+location.get("lng")+","+location.get("lat")+";";
			}
	        oldBean.setLngLatList(lngLatList);
	        oldBean = buildCoreLngLat(oldBean);
		}
		
		return oldBean;
	}
	
	/**
	 * @desc 转换中心点经纬度
	 * @param oldBean
	 * @return
	 */
	private static TmpXqBean buildCoreLngLat(TmpXqBean oldBean){
		String lng = oldBean.getLng();
		String lat = oldBean.getLat();
		
		if (lng !=null && lat!=null) {
			double tLng =  Double.valueOf(lng);
			double tLat = Double.valueOf(lat);
			Map<String, Double> location = convertMC2LL(tLng, tLat);
			oldBean.setLng(String.valueOf(location.get("lng")));
			oldBean.setLat(String.valueOf(location.get("lat")));
		}
		
		return oldBean;
		
	}

	
	/**
	 * @desc 根据名称搜索uid列表
	 * @param xqName
	 * @return
	 */
	@SuppressWarnings({ "deprecation", "unchecked" })
	private static List<String> getUids(String name){
		List< String> uids = new ArrayList<>();
		String tmpUidUrl = uidUrl.replace("$xqName$", name);
		tmpUidUrl =  encodeUrl(tmpUidUrl);
		try {
			String result = HttpUtils.sendGet(tmpUidUrl, "");
			JSONObject jObj = JSONObject.fromObject(result);
			JSONArray uidArr = jObj.getJSONArray("s");
			uids = JSONArray.toList(uidArr);
		} catch (Exception e) {
			e.printStackTrace();
			return null;
		}
		
		return uids;
	}
	
	
	/**
	 * @desc 根据名称搜索uid列表
	 * @param xqName
	 * @return
	 */
	@SuppressWarnings({ "deprecation", "unchecked" })
	private static List<String> getUids2(String name){
		List< String> uids = new ArrayList<>();
		String tmpUidUrl = uidUrl2.replace("$xqName$", name);
		tmpUidUrl =  encodeUrl(tmpUidUrl);
		try {
			String result = HttpUtils.sendGet(tmpUidUrl, "");
			JSONObject jObj = JSONObject.fromObject(result);
			JSONArray uidArr = jObj.getJSONArray("content");
			for (int i = 0; i < uidArr.size(); i++) {
				JSONObject uidObj = (JSONObject) uidArr.get(i);
				String uidStr = "$"+"$"+"$"+uidObj.getString("name")+"$"+"$"+uidObj.getString("uid")+"$";
				uids.add(uidStr);
			}
			
		} catch (Exception e) {
			e.printStackTrace();
			return null;
		}
		
		return uids;
	}
	
	/**
	 * @desc 根据uid获取墨卡托坐标边界
	 * @param uid
	 * @return
	 */
	private static Map<String, String> getGeo(String uid){
		Map<String, String> geoMap = new HashMap<String, String>();
		String tmpGeoUrl = geoUrl.replace("$UID$", uid);
		tmpGeoUrl =  encodeUrl(tmpGeoUrl);
		try {
			String result = HttpUtils.sendGet(tmpGeoUrl, "");
			JSONObject jObj = JSONObject.fromObject(result);
			JSONObject contentObj	 = jObj.getJSONObject("content");
			String geoStr = contentObj.getString("geo");
			String geoResult = "";
			String coreResult = "";
			if (geoStr!=null && !geoStr.trim().equals("")) {
				geoResult = geoStr.substring(geoStr.indexOf("|1-")+3, geoStr.length()-1);
				
				String coreStr = geoStr.substring(2,geoStr.indexOf("|1-"));
				String coreLng1 = coreStr.split(";")[0].split(",")[0];
				String coreLat1 = coreStr.split(";")[0].split(",")[1];
				
				String coreLng2 = coreStr.split(";")[1].split(",")[0];
				String coreLat2 = coreStr.split(";")[1].split(",")[1];
				
				DecimalFormat decimalFormat = new DecimalFormat("###0.00");//格式化设置
				double coreLng = (Double.valueOf(coreLng1)+Double.valueOf(coreLng2))/2 ;
				double coreLat =  (Double.valueOf(coreLat1)+Double.valueOf(coreLat2))/2  ;
				coreResult = decimalFormat.format(coreLng)+","+decimalFormat.format(coreLat);
			}
			geoMap.put("geo", geoResult);
			geoMap.put("core", coreResult);
		} catch (Exception e) {
			e.printStackTrace();
			return new HashMap<String, String>();
		}
		
		return geoMap;
	}
	
	private static String encodeUrl(String url){
		url = url.replaceAll(" ", "%20");
		url = url.replaceAll("\\{", "%7B");
		url = url.replaceAll("\\}", "%7D");
		return url;
	}
	
	
	/**
     * 墨卡托坐标转经纬度坐标
     * @param x
     * @param y
     * @return
     */
    public static Map<String, Double> convertMC2LL(Double x, Double y) {
        Double[] cF = null;
        x = Math.abs(x);
        y = Math.abs(y);

        for (int cE = 0; cE < MCBAND.length; cE++) {
            if (y >= MCBAND[cE]) {
                cF = MC2LL[cE];
                break;
            }
        }
        Map<String,Double> location = converter(x, y, cF);
        location.put("lng",location.get("x"));
        location.remove("x");
        location.put("lat",location.get("y"));
        location.remove("y");
        return location;
    }


    /**
     * 经纬度坐标转墨卡托坐标
     * @param lng
     * @param lat
     * @return
     */
    private static Map<String, Double> convertLL2MC(Double lng, Double lat) {
        Double[] cE = null;
        lng = getLoop(lng, -180, 180);
        lat = getRange(lat, -74, 74);
        for (int i = 0; i < LLBAND.length; i++) {
            if (lat >= LLBAND[i]) {
                cE = LL2MC[i];
                break;
            }
        }
        if (cE!=null) {
            for (int i = LLBAND.length - 1; i >= 0; i--) {
                if (lat <= -LLBAND[i]) {
                    cE = LL2MC[i];
                    break;
                }
            }
        }
        return converter(lng,lat, cE);
    }


    private static Map<String, Double> converter(Double x, Double y, Double[] cE) {
        Double xTemp = cE[0] + cE[1] * Math.abs(x);
        Double cC = Math.abs(y) / cE[9];
        Double yTemp = cE[2] + cE[3] * cC + cE[4] * cC * cC + cE[5] * cC * cC * cC + cE[6] * cC * cC * cC * cC + cE[7] * cC * cC * cC * cC * cC + cE[8] * cC * cC * cC * cC * cC * cC;
        xTemp *= (x < 0 ? -1 : 1);
        yTemp *= (y < 0 ? -1 : 1);
        Map<String, Double> location = new HashMap<String, Double>();
        location.put("x", xTemp);
        location.put("y", yTemp);
        return location;
    }

    private static Double getLoop(Double lng, Integer min, Integer max) {
        while (lng > max) {
            lng -= max - min;
        }
        while (lng < min) {
            lng += max - min;
        }
        return lng;
    }

    private static Double getRange(Double lat, Integer min, Integer max) {
        if (min != null) {
            lat = Math.max(lat, min);
        }
        if (max != null) {
            lat = Math.min(lat, max);
        }
        return lat;
    }
	
	public static void main(String[] args) {
		
		TmpXqBean oldBean = new TmpXqBean();
		oldBean.setName("府前官邸小区");
		TmpXqBean newBean = convert(oldBean);
		if (newBean == null) {
			System.out.println("获取边界失败");
			return;
		}
		System.out.println(newBean.getGeo());
		System.out.println(newBean.getLngLatList());
		System.out.println(newBean.getLng()+"||"+newBean.getLat());
	}

}
